package com.icongyou.enterprise.talent_analysis.service;

import com.icongyou.enterprise.talent_analysis.entity.WordCloudCache;
import com.icongyou.enterprise.talent_analysis.mapper.WordCloudCacheMapper;
import com.icongyou.enterprise.talent_analysis.service.impl.WordCloudServiceImpl;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.icongyou.enterprise.talent_analysis.mapper.WordCloudUpdateQueueMapper;
import com.icongyou.enterprise.talent_analysis.service.AIPortraitEvaluationService;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;

import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;

import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.ArgumentMatchers.*;
import static org.mockito.Mockito.*;

/**
 * 词云服务测试
 */
@ExtendWith(MockitoExtension.class)
@DisplayName("词云服务测试")
class WordCloudCacheServiceImplTest {

    @Mock
    private WordCloudCacheMapper cacheMapper;
    
    @Mock
    private WordCloudUpdateQueueMapper queueMapper;
    
    @Mock
    private AIPortraitEvaluationService aiPortraitService;
    
    @Mock
    private ObjectMapper objectMapper;

    @InjectMocks
    private WordCloudServiceImpl service;

    @BeforeEach
    void setUp() {
        // Mock对象自动注入
    }

    @Test
    @DisplayName("获取词云 - 缓存命中")
    void testGetWordCloud_Hit() throws Exception {
        // Arrange
        String studentId = "student-1";
        Map<String, Integer> keywords = new HashMap<>();
        keywords.put("Java", 10);
        
        WordCloudCache cache = createValidCache(studentId);
        
        when(cacheMapper.selectByStudentId(studentId))
            .thenReturn(cache);
        when(objectMapper.readValue(anyString(), any(com.fasterxml.jackson.core.type.TypeReference.class)))
            .thenReturn(keywords);

        // Act
        Map<String, Integer> result = service.getWordCloud(studentId);

        // Assert
        assertNotNull(result);
        verify(cacheMapper).selectByStudentId(studentId);
    }

    @Test
    @DisplayName("获取词云 - 缓存不存在,同步生成")
    void testGetWordCloud_Miss_GenerateSync() throws Exception {
        // Arrange
        String studentId = "student-1";
        Map<String, Integer> keywords = new HashMap<>();
        keywords.put("Python", 8);
        
        when(cacheMapper.selectByStudentId(studentId))
            .thenReturn(null);
        when(aiPortraitService.extractTeacherCommentKeywords(studentId))
            .thenReturn(keywords);
        when(objectMapper.writeValueAsString(any())).thenReturn("{}");

        // Act
        Map<String, Integer> result = service.generateWordCloudSync(studentId);

        // Assert
        assertNotNull(result);
        assertEquals(1, result.size());
    }

    @Test
    @DisplayName("异步生成词云任务")
    void testGenerateWordCloudAsync() {
        // Arrange
        String studentId = "student-1";
        when(queueMapper.insert(any())).thenReturn(1);

        // Act
        service.generateWordCloudAsync(studentId, "MANUAL", "TEST");

        // Assert
        verify(queueMapper).insert(any());
    }

    @Test
    @DisplayName("清除学生词云缓存")
    void testInvalidateCache() {
        // Arrange
        String studentId = "student-1";
        when(cacheMapper.deleteByStudentId(studentId)).thenReturn(1);

        // Act
        service.invalidateCache(studentId);

        // Assert
        verify(cacheMapper).deleteByStudentId(studentId);
    }

    // ==================== Helper Methods ====================

    private WordCloudCache createValidCache(String studentId) {
        WordCloudCache cache = new WordCloudCache();
        cache.setStudentId(studentId);
        cache.setKeywordsJson("{\"Java\": 10}");
        cache.setAiUsed(true);
        cache.setGeneratedAt(LocalDateTime.now());
        cache.setUpdatedAt(LocalDateTime.now());
        cache.setVersion(0);
        return cache;
    }
}
